package ca.ubc.eece310.project;

/**
 * EECE 310 Term Project Fall 2009
 * @author Matthew Fong, Herman Lee, Scott Pearson
 */

import java.io.*;
import java.util.Calendar;
import java.util.GregorianCalendar;

public class Log extends Thread {
	/**
	 * OVERVIEW: This class will record the daily bandwidth usage into a file.
	 * 			 It should run in its own Thread
	 * Rep-Invariant: c.file != null
	 * AF(c): c.fw, c.filename, c.file, c.dateToday, c.dateLast, c.todaysTraffic
	 * 		  c.numDaysThisYear, c.numDaysThisMonth, c.dayLogData, c.MonthLogData
	 * 		  c.yearLogData
	 */

	private static FileWriter fw;
	private static String filename = "log.csv";
	private static File file = new File(filename);
	private static String dateToday, dateLast;
	private static long[] todaysTraffic = new long[2];
	private static int numDaysThisYear = 0;
	private static int numDaysThisMonth = 0;
	public static LogTableModel dayLogData = new LogTableModel(0);
	public static LogTableModel monthLogData = new LogTableModel(1);
	public static LogTableModel yearLogData = new LogTableModel(2);

	// CONSTRUCTOR
	public Log() {
	}

	public void run() {
		/*******************************************************************************
		 * MODIFIES: totalBytesDownToday from main class, totalBytesUpToday from
		 * 			 main class, file log.csv, dateToday, dateLast, todaysTraffic 
		 * EFFECTS:  Opens "log.csv" and appends the accumulated traffic today to it
		 *******************************************************************************/

		Calendar c = new GregorianCalendar();
		// get today's date, and store it in a "history" variable
		dateToday = c.get(Calendar.DAY_OF_MONTH) + "/"
				 + (c.get(Calendar.MONTH) + 1)   + "/" + c.get(Calendar.YEAR);
		dateLast = dateToday;

		// try to create a file writer and scanner
		try {
			fw = new FileWriter(file, true); 
		} catch (IOException e) {
			// it failed, so create it
			try {
				file.createNewFile();
				fw = new FileWriter(file, true); 
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}

		// if it is a new file, write today's date
		if (file.length() == 0) {
			try {
				fw.write(dateToday);
				fw.write(",");
				fw.write(BandwidthLog.totalBytesDownToday + ","
						+ BandwidthLog.totalBytesUpToday);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		todaysTraffic = findTodaysTraffic();
		BandwidthLog.totalBytesDownToday = todaysTraffic[0];
		BandwidthLog.totalBytesUpToday = todaysTraffic[1];

		while (true) {
			dateToday = c.get(Calendar.DAY_OF_MONTH) + "/"
					 + (c.get(Calendar.MONTH) + 1) +   "/" + c.get(Calendar.YEAR);

			// get the number of days recorded this year, and this month
			numDaysThisMonth = 0;
			numDaysThisYear = 0;
			Object[][] data=dayLogData.getData();
			for(int i=0; i<data.length-1; i++) {
				if(data[i][0].toString().contains(c.get(Calendar.MONTH)+ "/" + c.get(Calendar.YEAR)))
					numDaysThisMonth++;
				if(data[i][0].toString().contains(Integer.toString(c.get(Calendar.YEAR))))
					numDaysThisYear++;
			}
			// if the last date recorded is not today, set those to 0 
			if (!dateToday.equals(dateLast)) {
				BandwidthLog.totalBytesDownToday = 0L;
				BandwidthLog.totalBytesUpToday = 0L;
			}
			dateLast = dateToday;
			try {
				fw.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			// remove the line with today's date in it and then write it back with update data
			removeLineFromFile(dateToday);
			try {
				fw = new FileWriter(file, true);
				fw.write(dateToday);
				fw.write(",");
				fw.write(BandwidthLog.totalBytesDownToday + "," + BandwidthLog.totalBytesUpToday + "\n");
				fw.close();

				// update all the tables
				dayLogData.updateTable();
				dayLogData.fireTableDataChanged();
				monthLogData.updateTable();
				monthLogData.fireTableDataChanged();
				yearLogData.updateTable();
				yearLogData.fireTableDataChanged();
				
				Thread.sleep(1000); 
			} catch (InterruptedException e) { 
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static long[] findTodaysTraffic() {
		/**
		 * EFFECTS: Finds the amount of traffic today from "log.csv" and returns
		 * it in a long[] where long[0] = traffic down and long[1] = traffic up
		 */
		long[] downUp = { 0, 0 };
		try {

			if (!file.isFile()) {
				System.out.println("Parameter is not an existing file");
				return null;
			}

			BufferedReader br = new BufferedReader(new FileReader(filename));

			String line = null;

			// read the file and parse it
			while ((line = br.readLine()) != null) {
				if (line.contains(dateToday)) {
					downUp[0] = Long.parseLong((String) line.subSequence(line
							.indexOf(",") + 1, line.indexOf(",", line
							.indexOf(",") + 1)));
					downUp[1] = Long.parseLong((String) line.subSequence(line
							.lastIndexOf(",") + 1, line.length()));
				}
			}
			br.close();

		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
		} catch (IOException ex) {
			ex.printStackTrace();
		}
		return downUp;
	}

	public static void removeLineFromFile(String lineToRemove) {
		/**
		 * REQUIRES: file != null MODIFIES: the file specified by file EFFECTS:
		 * Removes the line lineToRemove from the file specified by file
		 */
		try {

			if (!file.isFile()) {
				System.out.println("Parameter is not an existing file");
				return;
			}

			// Construct the new file that will later be renamed to the original
			// filename.
			File tempFile = new File(file.getAbsolutePath() + ".tmp");

			BufferedReader br = new BufferedReader(new FileReader(filename));
			PrintWriter pw = new PrintWriter(new FileWriter(tempFile));

			String line = null;

			// Read from the original file and write to the new
			// unless content matches data to be removed.
			while ((line = br.readLine()) != null) {
				if (!line.contains(lineToRemove)) {

					pw.println(line);
					pw.flush();
				}
			}
			pw.close();
			br.close();

			// Delete the original file
			if (!file.delete()) {
				System.out.println("Could not delete file");
				return;
			}

			// Rename the new file to the filename the original file had.
			if (!tempFile.renameTo(file))
				System.out.println("Could not rename file");

			// delete the temp file
			tempFile.delete();

		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}

	public static void save() {
		/**
		 * EFFECTS: Saves the log file
		 */
		Calendar c = new GregorianCalendar();
		dateToday = c.get(Calendar.DAY_OF_MONTH) + "/"
				+ (c.get(Calendar.MONTH) + 1) + "/" + c.get(Calendar.YEAR);
		if (!dateToday.equals(dateLast)) {
			BandwidthLog.totalBytesDownToday = 0L;
			BandwidthLog.totalBytesUpToday = 0L;
		}
		dateLast = dateToday;
		try {
			fw.close();
		} catch (IOException e1) { }
		removeLineFromFile(dateToday);

		try {
			fw = new FileWriter(file, true);
			fw.write(dateToday);
			fw.write(",");
			fw.write(BandwidthLog.totalBytesDownToday + ","
					+ BandwidthLog.totalBytesUpToday + "\n");
			fw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static int getLogFileSize() {
		int numLines = 0;

		try {
			BufferedReader br = new BufferedReader(new FileReader(filename));
			
			while (br.readLine() != null) 
				numLines++;

			br.close();
		} catch (FileNotFoundException e) {

		} catch (IOException e) {
			System.out.println("couldn't find file");
		}
		
		return numLines;
	}

	public static File getLogFile() {
		return file;
	}
	
	public static String getLogFileName() {
		return filename;
	}
	
	public static int getNumLoggedDaysThisMonth() {
		return numDaysThisMonth;
	}
	
	public static int getNumLoggedDaysThisYear() {
		return numDaysThisYear;
	}
	
	public static boolean repOk() {
		/**
		 * EFFECTS: Returns true if the rep invariant holds for this
		 * 			else returns false
		 */
		if(file!=null)
			return true;
		return false;
	}
	
	public String toString() {
		/**
		 * EFFECTS: Returns a String representation
		 */
		return dayLogData.toString() + " " + monthLogData.toString() + " " + yearLogData.toString();
	}
}
